package com.yanmaohu.yulia;

/**
 * @author Bright Lee
 */
public final class YuliaException extends RuntimeException {

    public YuliaException(String sql, int firstLineNumber, int index, String message) {
        super(desc(sql, firstLineNumber, index, message));
    }

    public YuliaException(String sql, int firstLineNumber, int index, String message, Throwable cause) {
        super(desc(sql, firstLineNumber, index, message), cause);
    }

    private static String desc(String sql, int firstLineNumber, int index, String message) {
        int lineBeginIndex = getLineBeginIndex(sql, index);
        int lineEndIndex = getLineEndIndex(sql, index);
        int lineNumber = getLineNumber(sql, firstLineNumber, index);
        String lineNumberStr = String.valueOf(lineNumber);
        String line1 = sql.substring(lineBeginIndex, lineEndIndex);
        String line2 = sql.substring(lineBeginIndex, index);
        StringBuilder buf = new StringBuilder();
        buf.append("错误信息：").append(message).append('\n');
        buf.append(lineNumberStr).append(' ').append(line1).append('\n');
        for (int i = 0; i < lineNumberStr.length(); i++) {
            buf.append(' ');
        }
        buf.append(' ').append(line2);
        return buf.toString();
    }

    private static int getLineBeginIndex(String sql, int index) {
        if (sql.isEmpty() || index <= 0) {
            return 0;
        }
        int lineBeginIndex = 0;
        for (int i = index - 1; i >= 0; i--) {
            char c = sql.charAt(i);
            if (c == '\r' || c == '\n') {
                lineBeginIndex = i + 1;
                break;
            }
        }
        return lineBeginIndex;
    }

    private static int getLineEndIndex(String sql, int index) {
        if (sql.isEmpty() || index >= sql.length()) {
            return sql.length();
        }
        int lineEndIndex = sql.length();
        for (int i = index + 1; i < sql.length(); i++) {
            char c = sql.charAt(i);
            if (c == '\r' || c == '\n') {
                lineEndIndex = i - 1;
                break;
            }
        }
        return lineEndIndex;
    }

    private static int getLineNumber(String sql, int firstLineNumber, int index) {
        int lineNumber = firstLineNumber;
        for (int i = 0; i < index; i++) {
            int c = sql.charAt(i);
            if (c == '\n') {
                lineNumber++;
                continue;
            }
            if (c == '\r') {
                lineNumber++;
                if (i >= index - 1) {
                    break;
                }
                int c1 = sql.charAt(i + 1);
                if (c1 == '\r') {
                    continue;
                }
                if (c1 == '\n') {
                    i++;
                }
            }
        }
        return lineNumber;
    }

}
